﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using FinApp.Core;

namespace FinApp.DataProviders {
    public class ChryptoProvider : Singleton<ChryptoProvider> {

        #region Methods
        /// <summary>
        /// Encripta el string usando AES
        /// </summary>
        /// <param name="stringToEncrypt">El string a encriptar</param>
        /// <param name="password">Password para la encriptación</param>
        /// <param name="salt">El string que hace de sal</param>
        /// <returns>El string encriptado si ha ido bien; Cualquier otro caso, string vacío</returns>
        public string EncryptString(string stringToEncrypt, string password, string salt) {
            try {
                using (Aes aes = new AesManaged()) {
                    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
                    aes.Key = deriveBytes.GetBytes(128 / 8);
                    aes.IV = aes.Key;
                    using (MemoryStream encryptionStream = new MemoryStream()) {
                        using (CryptoStream encrypt = new CryptoStream(encryptionStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) {
                            byte[] utfD1 = UTF8Encoding.UTF8.GetBytes(stringToEncrypt);
                            encrypt.Write(utfD1, 0, utfD1.Length);
                            encrypt.FlushFinalBlock();
                        }
                        return Convert.ToBase64String(encryptionStream.ToArray());
                    }
                }
            } catch {
                return string.Empty;
            }
        }

        /// <summary>
        /// Desencripta el string subministrado a partir del password subministrado
        /// </summary>
        /// <param name="Str">El string encriptado</param>
        /// <param name="Password">Password para la desencriptación</param>
        /// <param name="Salt">El string que hace de sal</param>
        /// <returns>El string desencriptado si ha ido bien; Cualquier otro caso, string vacío</returns>
        public string DecryptString(string Str, string Password, string Salt) {
            try {
                using (Aes aes = new AesManaged()) {
                    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Password, Encoding.UTF8.GetBytes(Salt));
                    aes.Key = deriveBytes.GetBytes(128 / 8);
                    aes.IV = aes.Key;
                    using (MemoryStream decryptionStream = new MemoryStream()) {
                        using (CryptoStream decrypt = new CryptoStream(decryptionStream, aes.CreateDecryptor(), CryptoStreamMode.Write)) {
                            byte[] encryptedData = Convert.FromBase64String(Str);
                            decrypt.Write(encryptedData, 0, encryptedData.Length);
                            decrypt.Flush();
                        }
                        byte[] decryptedData = decryptionStream.ToArray();
                        return UTF8Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
                    }
                }
            } catch {
                return string.Empty;
            }
        } 
        #endregion

    }
}
